using UniqueVectors
using Compat.Test

using Compat

@test length(UniqueVector([1,5,6,3])) == 4
@test_throws ArgumentError UniqueVector([1,3,5,6,3])

uv = UniqueVector{String}()

@test isempty(uv)
@test_throws ArgumentError pop!(uv)
@test findfirst(equalto("cat"), uv) == 0
@test findfirst!(equalto("cat"), uv) == 1
@test !isempty(uv)
@test "cat" in uv
@test "dog" ∉ uv
@test count(equalto("cat"), uv) == 1
@test count(equalto("dog"), uv) == 0
@test find(equalto("cat"), uv) == [1]
@test find(equalto("dog"), uv) == Int[]
@test findfirst!(equalto("dog"), uv) == 2
@test findfirst!(equalto("cat"), uv) == 1
@test findfirst!(equalto("mouse"), uv) == 3
@test findfirst!(equalto("dog"), uv) == 2
@test findfirst(equalto("cat"), uv) == 1
@test findlast(equalto("cat"), uv) == 1
@test findfirst(equalto("dog"), uv) == 2
@test findfirst(equalto("mouse"), uv) == 3
@test uv[1] == "cat"
@test uv[2] == "dog"
@test uv[3] == "mouse"
@test uv[:] == ["cat", "dog", "mouse"]
@test size(uv) == (3,)
@test length(uv) == 3
@test endof(uv) == 3

uv2 = UniqueVector([1, 2, 3])
@test findfirst(equalto(0x02), uv2) == 2
@test findfirst!(equalto(0x02), uv2) == 2
@test uv2 == UniqueVector(i for i in 1:3)
for elt in [3,2,1]
    @test pop!(uv2) == elt
end
@test isempty(uv2)

uv2 = copy(uv)
@test uv2 == uv

@test empty!(uv) === uv
@test isempty(uv)
@test findfirst(equalto("cat"), uv) == 0
@test findfirst!(equalto("horse"), uv) == 1
@test_throws ArgumentError push!(uv, "horse")
@test length(uv) == 1
@test push!(uv, "human") === uv
@test findfirst(equalto("human"), uv) == 2
@test pop!(uv) == "human"
@test length(uv) == 1
@test uv[:] == ["horse"]
@test findfirst(equalto("human"), uv) == 0

@test uv2[:] == ["cat", "dog", "mouse"]
@test findfirst(equalto("cat"), uv2) == 1

let uv = UniqueVector(["cat", "dog", "mouse", "human"]), original = copy(uv)

    uv = swap!(uv, 2, 2)

    @test uv == original
    @test_throws BoundsError swap!(uv, 5, 5)

    swap!(uv, 2, 3)

    @test findfirst(equalto("mouse"), uv) == 2
    @test findfirst(equalto("mouse"), original) == 3

    @test findfirst(equalto("dog"), uv) == 3
    @test findfirst(equalto("dog"), original) == 2
end

@test UniqueVector([1,2,3,4]) == UniqueVector(1:4)

# Test it works with `Any` datatype
let uv3 = UniqueVector([1,"cat",2,"dog"])
    @test eltype(uv3) == Any
    @test findfirst(equalto(1), uv3) == 1
    @test findlast(equalto(1), uv3) == 1
    @test find(equalto(1), uv3) == [1]
    @test count(equalto(1), uv3) == 1
    @test findfirst!(equalto("dog"), uv3) == 4
    @test findfirst!(equalto("horse"), uv3) == 5
end

# Test setindex!
uv4 = UniqueVector(["cat", "dog", "mouse"])
@test_throws BoundsError uv4[4] = "horse"
uv4[2] = "horse"
uv4[3] = "dog"
@test uv4[:] == ["cat", "horse", "dog"]
uv4[1] = "cat"
@test_throws ArgumentError uv4[2] = "dog"
push!(uv4, "mouse")
@test uv4[:] == ["cat", "horse", "dog", "mouse"]
@test uv4[1:2] == ["cat", "horse"]

uv5 = UniqueVector{Float64}()
push!(uv5, 3)
@test uv5[:] == [3.0]
uv5[1] = 4
@test uv5[:] == [4.0]
@test 4 ∈ uv5
@test findfirst(equalto(4), uv5) == 1
@test findlast(equalto(4), uv5) == 1
@test find(equalto(4), uv5) == [1]

# Test indexin and findin
@test indexin([1,2,34,0,5,56], UniqueVector([34,56,35,1,5,0])) == [4,0,1,6,5,2]
@test findin([1,2,34,0,5,56], UniqueVector([34,56,35,1,5,0])) == [1,3,4,5,6]

# Test findnext and findprev
@test findnext(equalto(7), UniqueVector([3,5,7,9]), 1) == 3
@test findnext(equalto(7), UniqueVector([3,5,7,9]), 2) == 3
@test findnext(equalto(7), UniqueVector([3,5,7,9]), 3) == 3
@test findnext(equalto(7), UniqueVector([3,5,7,9]), 4) == 0
@test findprev(equalto(7), UniqueVector([3,5,7,9]), 1) == 0
@test findprev(equalto(7), UniqueVector([3,5,7,9]), 2) == 0
@test findprev(equalto(7), UniqueVector([3,5,7,9]), 3) == 3
@test findprev(equalto(7), UniqueVector([3,5,7,9]), 4) == 3
